package net.ufrog.common.utils;

import net.ufrog.common.CoreConfig;

import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 字符串工具
 * 
 * @author ultrafrog
 * @version	1.0, 2011-12-19
 * @since 1.0
 */
public class Strings {

    /** 构造函数 */
    private Strings() {}

    /**
     * 判定是否为空
     *
     * @param str 待判定字符串
     * @return 判定结果
     */
    public static boolean empty(String str) {
        return (str == null || str.length() == 0);
    }

    /**
     * 判定是否为空<br>
     * 如果为空则返回默认值
     *
     * @param str 待判定字符串
     * @param defaultValue 空时返回默认值
     * @return 非空字符串或默认值
     */
    public static String empty(String str, String defaultValue) {
        return empty(str) ? defaultValue : str;
    }

    /**
     * 判定是否为空白
     *
     * @param str 待判定字符串
     * @return 判定结果
     */
    public static boolean blank(String str) {
        return (str == null || str.trim().length() == 0);
    }

    /**
     * 判定是否为空白<br>
     * 如果为空白则返回默认值
     *
     * @param str 待判定字符串
     * @param defaultValue 空白时返回默认值
     * @return 非空白字符串或默认值
     */
    public static String blank(String str, String defaultValue) {
        return blank(str) ? defaultValue : str;
    }

    /**
     * 判定是否相同
     *
     * @param one 待判定字符串
     * @param another 待判定字符串
     * @return 判定结果
     * @see java.lang.String#equals(Object)
     */
    public static boolean equals(String one, String another) {
        return (one == another || (one != null && one.equals(another)));
    }

    /**
     * 判定字符串是否是UUID
     *
     * @param str 待判定字符串
     * @return 判定结果
     */
    public static boolean uuid(String str) {
        return !empty(str) && CoreConfig.getPatternUUID().matcher(str).matches();
    }

    /**
     * 判定字符串是否为手机号码
     *
     * @param str 待判定字符串
     * @return 判定结果
     */
    public static boolean cellphone(String str) {
        return !empty(str) && CoreConfig.getPatternCellphone().matcher(str).matches();
    }

    /**
     * 判定字符串是否邮件地址
     *
     * @param str 待判定字符串
     * @return 判定结果
     */
    public static boolean email(String str) {
        return !empty(str) && CoreConfig.getPatternEmail().matcher(str).matches();
    }

    /**
     * 判定字符串是否在数组中
     *
     * @param str 待判定字符串
     * @param strs 字符串数组
     * @return 判定结果
     */
    public static boolean in(String str, String... strs) {
        List<String> lStr = Stream.of(strs).filter(s -> equals(s, str)).collect(Collectors.toList());
        return lStr.size() > 0;
    }

    /**
     * 首字母大写
     *
     * @param str 字符串
     * @return 处理后字符串
     */
    public static String toTitleCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] = Character.toUpperCase(chars[0]);
        return new String(chars);
    }

    /**
     * 首字母小写
     *
     * @param str 字符串
     * @return 处理后字符串
     */
    public static String toLowerTitleCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

    /**
     * 驼峰命名
     *
     * @param str 字符串
     * @param regex 间隔符
     * @return 处理后字符串
     */
    public static String toCamelCase(String str, String regex) {
        StringBuilder name = builder();
        explode(str, regex).forEach(s -> name.append(toTitleCase(s.toLowerCase())));
        return toLowerTitleCase(name.toString());
    }

    /**
     * 转换字符串编码<br>
     * 从<code>ISO-8859-1</code>转换成<code>UTF-8</code>
     *
     * @param str 字符串
     * @return 转换后字符串
     */
    public static String toUTF8(String str) {
        return convertStrEncode(str, "ISO-8859-1", "UTF-8");
    }

    /**
     * 转换字符串编码
     *
     * @param str 字符串
     * @param fromEncode 源编码
     * @param toEncode 目标编码
     * @return 转换编码后字符串
     */
    public static String convertStrEncode(String str, String fromEncode, String toEncode) {
        return Strings.empty(str) ? str : new String(str.getBytes(Charset.forName(fromEncode)), Charset.forName(toEncode));
    }

    /**
     * 随机字符串
     *
     * @param length 字符串长度
     * @param sets 字符串数组
     * @return 随机生成的字符串
     */
    public static String random(int length, String... sets) {
        String[] strs = (sets == null || sets.length == 0) ? array(StringSet.NUMERIC, StringSet.LOWER_ALPHABET, StringSet.UPPER_ALPHABET) : sets;
        StringBuilder result = builder(length);
        StringBuilder builder = builder(strs);
        Random random = new Random();

        IntStream.range(0, length).forEach(idx -> result.append(builder.charAt(random.nextInt(builder.length()))));
        return result.toString();
    }

    /**
     * 截断
     *
     * @param str 字符串
     * @param len 截断长度
     * @param suffix 后缀
     * @return 截断后字符串
     */
    public static String truncate(String str, int len, String suffix) {
        return (empty(str) || str.length() <= len) ? str : str.substring(0, len) + empty(suffix, "");
    }

    /**
     * 拆分
     *
     * @param str 字符串
     * @param regex 间隔符
     * @return 字符串列表
     */
    public static List<String> explode(String str, String regex) {
        return Arrays.asList(str.split(regex));
    }

    /**
     * 合并
     *
     * @param objs 对象集合
     * @param symbol 间隔符
     * @return 合并后字符串
     */
    public static String implode(Collection<?> objs, String symbol) {
        return  objs.stream().map(String::valueOf).collect(Collectors.joining(symbol));
    }

    /**
     * 转换数组
     *
     * @param strs 字符串数组
     * @return 字符串数组
     */
    public static String[] array(String... strs) {
        return strs;
    }

    /**
     * 创建 <code>StringBuffer</code> 实例
     *
     * @param capacity 容量
     * @return 字符串缓冲
     * @see java.lang.StringBuffer
     */
    public static StringBuffer buffer(int capacity) {
        return new StringBuffer(capacity);
    }

    /**
     * 创建 <code>StringBuffer</code> 实例
     *
     * @param str 字符串
     * @return 字符串缓冲
     * @see java.lang.StringBuffer
     */
    public static StringBuffer buffer(String str) {
        return buffer((str.length() + 1) * 2).append(str);
    }

    /**
     * 创建 <code>StringBuffer</code> 实例
     *
     * @return 字符串缓冲
     * @see java.lang.StringBuffer
     */
    public static StringBuffer buffer() {
        return buffer(16);
    }

    /**
     * 创建 <code>StringBuffer</code> 实例
     *
     * @param strs 字符串数组
     * @return 字符串缓冲
     */
    public static StringBuffer buffer(String... strs) {
        StringBuffer buffer = buffer();
        Stream.of(strs).forEach(buffer::append);
        return buffer;
    }

    /**
     * 创建 <code>StringBuilder</code> 实例
     *
     * @param capacity 容量
     * @return 字符串构造器
     * @see java.lang.StringBuilder
     */
    public static StringBuilder builder(int capacity) {
        return new StringBuilder(capacity);
    }

    /**
     * 创建 <code>StringBuilder</code> 实例
     *
     * @param str 字符串
     * @return 字符串构造器
     * @see java.lang.StringBuilder
     */
    public static StringBuilder builder(String str) {
        return builder((str.length() + 1) * 2).append(str);
    }

    /**
     * 创建 <code>StringBuilder</code> 实例
     *
     * @return 字符串构造器
     * @see java.lang.StringBuilder
     */
    public static StringBuilder builder() {
        return builder(16);
    }

    /**
     * 创建 <code>StringBuilder</code> 实例
     *
     * @param strs 字符串数组
     * @return 字符串构造器
     */
    public static StringBuilder builder(String... strs) {
        StringBuilder builder = builder();
        Stream.of(strs).forEach(builder::append);
        return builder;
    }

    /**
     * 转换成字符串
     *
     * @param obj 对象
     * @return 字符串
     */
    public static String toString(Object obj) {
        if (obj instanceof String) {
            String str = String.class.cast(obj);
            if (str.length() > 100) return str.length() + " chars string.";
        } else if (obj instanceof List) {
            List<?> list = List.class.cast(obj);
            if (list.size() > 10) return list.size() + " size list.";
        } else if (obj instanceof Map) {
            Map<?, ?> map = Map.class.cast(obj);
            if (map.size() > 5) return map.size() + " size map.";
        }
        return String.valueOf(obj);
    }

    /**
     * 转换成<code>Unicode</code>
     *
     * @param str 字符串
     * @return 字符串
     */
    public static String toUnicode(String str) {
        if (empty(str)) return str;
        StringBuilder builder = builder();
        for (Character ch: str.toCharArray()) {
            builder.append((ch < 256) ? ch : "\\u" + Integer.toHexString(ch & 0xffff));
        }
        return builder.toString();
    }

    /**
     * 从<code>Unicode</code>转换
     *
     * @param str 字符串
     * @return 字符串
     */
    public static String fromUnicode(String str) {
        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()) {
            char ch = (char) Integer.parseInt(matcher.group(2), 16);
            str = str.replace(matcher.group(1), String.valueOf(ch));
        }
        return str;
    }

    /**
     * 字符串集合
     *
     * @author ultrafrog
     * @version 1.0, 2011-12-30
     * @since 1.0
     */
    public static final class StringSet {

        /** 数字 */
        public static final String NUMERIC			= "1234567890";

        /** 小写字母 */
        public static final String LOWER_ALPHABET 	= "abcdefghijklmnopqrstuvwxyz";

        /** 大写字母 */
        public static final String UPPER_ALPHABET 	= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        /** 符号 */
        public static final String SYMBOL			= "!@#$%^&*_+-=|:;?";
    }
}
